package com.TexasHoldem;

import java.io.IOException;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicLong;
import java.util.regex.Matcher;
import java.util.regex.Pattern;


import com.TexasHoldem.ServerData.PokerPlayer;
import com.TexasHoldem.ServerData.TableData;
import com.TexasHoldem.core.*;


import net.sf.json.JSONArray;
import net.sf.json.JSONObject;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.TexasHoldem.core.actions.*;
import org.xsocket.connection.IServer;
import org.xsocket.connection.Server;

import com.TexasHoldem.core.Table;
import com.TexasHoldem.core.actions.Action;
import com.TexasHoldem.util.ResourceBundleConfig;
import com.TexasHoldem.xSocket.data.CommonConstants;
import com.TexasHoldem.xSocket.engine.AbstractEngine;
import com.TexasHoldem.xSocket.engine.SocketHandler;

public class TexasHoldemServer extends AbstractEngine{

	 /** Table type (betting structure). */
    private static final TableType TABLE_TYPE = TableType.NO_LIMIT;

    /** The size of the big blind. */
    private static final int BIG_BLIND = 10;
    
    /** The starting cash per player. */
    private static final int STARTING_CASH = 5000;
    
    private Map<String, Player> players =  null;
    
	//扑克桌子
	private Map<Integer,Table> tablelist = new HashMap<Integer,Table>();

	private boolean shutdowned;
	
	private static final Log logger = LogFactory.getLog(TexasHoldemServer.class);
	
	//在线玩家
	private Map<Long,PokerPlayer> onlineplayers = new HashMap<Long,PokerPlayer>();
	
	private final AtomicLong ids = new AtomicLong(0);
	
	public static String CONFIG_FILE_NAME = "texasholdemserver";
	
	private final ResourceBundleConfig config = new ResourceBundleConfig(CONFIG_FILE_NAME);
	
	private static ExecutorService executeService;
	
	public static void main(String[] args) throws UnknownHostException, IOException
	{
		TexasHoldemServer texas = new TexasHoldemServer();
		IServer srv = new Server(1818, texas);
		
		srv.start();
		
		texas.init();
	}
	
	public void init()
	{
		
		
		players = new HashMap<String, Player>();
      
		int tablecount = Integer.parseInt(config.getProperty("tablecount"));
		
		int workcount = Integer.parseInt(config.getProperty("workcount"));
		executeService = Executors.newFixedThreadPool(workcount);
        
		for(int i = 0;i < tablecount;i++)
		{
			Table t = new Table(new TableConfig());
			tablelist.put(i + 1, t);
			executeService.execute(t);
		}
		
//		for(Table t:tablelist.values())
//		{
//			Thread background = new Thread(t);
//			background.start();
//		}
		
      
        
	}
	
	public void handleInternalRequest(String cmd, Object data,
			SocketHandler handler) {
		super.handleInternalRequest(cmd, data, handler);

		
	}	

	public void handleRequest(String cmd, JSONObject netdata, SocketHandler socketHandler) {
		
		System.out.print("[Server Rcv " + System.currentTimeMillis() + "]" + netdata.toString() + "\n");
		// 玩家登陆
		if (cmd.equals(CommonConstants.LOGIN_CMD)) 
		{
			
			JSONObject jsonobject = (JSONObject) netdata.get("data");
			String name = jsonobject.getString("name");
			Long id = ids.incrementAndGet();
			PokerPlayer p = new PokerPlayer(id);
			
			p.setName(name);
			p.setSockethandle(socketHandler);
			onlineplayers.put(id, p);
			socketHandler.setPokerplayer(p);
			
			List<TableData> l = new ArrayList<TableData>();
			for(Table t:this.tablelist.values())
			{
				TableData tb = new TableData();
				tb.setBigBlind(t.getTableCofing().getBigBlind());
				tb.setTablename("澳门新豪天地");
				tb.setTabletype("No Limit");
				l.add(tb);
			}
			JSONObject j = new JSONObject();
			j.put("id", id);
			j.put("list", l);
			System.out.println(CommonConstants.LOGIN_CMD + name);
			// send back table list
			socketHandler.sendResponse(CommonConstants.SERVER_TABLELIST, j.toString());
		}
		// 请求获取桌子列表
		else if(cmd.equals(CommonConstants.SERVER_GETTABLELIST))
		{
			List<TableData> l = new ArrayList<TableData>();
			for(Table t:this.tablelist.values())
			{
				TableData tb = new TableData();
				tb.setBigBlind(t.getTableCofing().getBigBlind());
				tb.setTablename("澳门新豪天地");
				tb.setTabletype("No Limit");
				l.add(tb);
			}
			// 下发扑克桌子列表
			socketHandler.sendResponse(CommonConstants.SERVER_TABLELIST, JSONArray.fromObject(l).toString());
		}
		// 进入扑克
		else if(cmd.equals(CommonConstants.SERVER_ENTERTABLE))
		{
			if(socketHandler.getPokerplayer() != null)
			{
				JSONObject jsonobject = (JSONObject) netdata.get("data");
				
				int tableid = (Integer) jsonobject.get("tableid");
				
				if(tableid != 0)
				{
					Table t = tablelist.get(tableid);
					if(t != null)
					{
						if(!socketHandler.getPokerplayer().getCurplaytable().containsKey(t.getTableCofing().getId()))
						{
							Player p = new Player(socketHandler.getPokerplayer().getName(), STARTING_CASH, socketHandler.getPokerplayer());
							socketHandler.getPokerplayer().getCurplaytable().put(t.getTableCofing().getId(), p);
							t.addPlayer(p);
							
							// 下发扑克桌子其他玩家信息
							socketHandler.sendResponse(CommonConstants.SERVER_TABLEPLAYERS, t.getOtherPlayersJson(p));
							// 通知其他玩家有新玩家进入牌桌
							t.notifyPlayerEnterTable(p);
						}
						
					}
					
					
					if(t.getPlayersCount() >= 2)
						t.setBstart(true);
				}
				else
				{
					
				}
				
				
				
			}
		}
		else if(cmd.equals(CommonConstants.SERVER_AUTOENTERTABLE))
		{
			Table havefree = null;
			synchronized (this.tablelist)
			{
				for(Table t:this.tablelist.values())
				{
					if(t.getPlayersCount() < t.getTableCofing().getLimitPlayerCount())
					{
						havefree = t;
						break;
					}
				}
			}
			if(havefree != null && !socketHandler.getPokerplayer().getCurplaytable().containsKey(havefree.getTableCofing().getId()))
			{
				Player p = new Player(socketHandler.getPokerplayer().getName(), STARTING_CASH, socketHandler.getPokerplayer());
				socketHandler.getPokerplayer().getCurplaytable().put(havefree.getTableCofing().getId(), p);
				havefree.addPlayer(p);
				
				// 下发扑克桌子其他玩家信息
				socketHandler.sendResponse(CommonConstants.SERVER_TABLEPLAYERS, havefree.getOtherPlayersJson(p));
				// 通知其他玩家有新玩家进入牌桌
				havefree.notifyPlayerEnterTable(p);
				System.out.print("enter table:" + havefree.getTableCofing().getId() + "," + p.getName() + "\n");
				if(havefree.getPlayersCount() >= 2)
					havefree.setBstart(true);
			}

		}
		// 当前玩家离开桌子
		else if(cmd.equals(CommonConstants.SERVER_LEAVE))
		{
			if(socketHandler.getPokerplayer() != null)
			{				
				JSONObject jsonobject = (JSONObject) netdata.get("data");
				
				int tableid = (Integer) jsonobject.get("tableid");
				
				if(socketHandler.getPokerplayer().getCurplaytable() != null)
				{
					Player p = socketHandler.getPokerplayer().getCurplaytable().get(tableid);
					if(p != null && this.tablelist.containsKey(tableid))
						this.tablelist.get(tableid).removePlayer(p);
					
					this.tablelist.get(tableid).notifyPlayerLeaveTable(p);
					
				}
				
			}
		}
		// 通知服务器有下注动作
		else if(cmd.equals(CommonConstants.SERVER_ACTION))
		{
			JSONObject jsonobject = (JSONObject) netdata.get("data");
			
			int type = (Integer) jsonobject.get("type");
			
			int tableid = (Integer) jsonobject.get("tableid");
			
			if(type == CommonConstants.ALL_IN)
			{
				if(socketHandler.getPokerplayer().getCurplaytable().containsKey(tableid))
				{
					Player p = socketHandler.getPokerplayer().getCurplaytable().get(tableid);
					p.setAction(Action.ALL_IN);
					synchronized (p) 
					{
						p.notifyAll();
				    }
				}
			}
			else if(type == CommonConstants.BET)
			{
				if(socketHandler.getPokerplayer().getCurplaytable().containsKey(tableid))
				{
					int amount = (Integer) jsonobject.get("amount");
					Player p = socketHandler.getPokerplayer().getCurplaytable().get(tableid);
					p.setAction( new BetAction(amount));
					synchronized (p) 
					{
						p.notifyAll();
				    }
				}
			}
			else if(type == CommonConstants.CALL)
			{
				if(socketHandler.getPokerplayer().getCurplaytable().containsKey(tableid))
				{
					Player p = socketHandler.getPokerplayer().getCurplaytable().get(tableid);
					p.setAction(Action.CALL);
					synchronized (p) 
					{
						p.notifyAll();
				    }
				}
			}
			else if(type == CommonConstants.CHECK)
			{
				if(socketHandler.getPokerplayer().getCurplaytable().containsKey(tableid))
				{
					Player p = socketHandler.getPokerplayer().getCurplaytable().get(tableid);
					p.setAction( Action.CHECK);
					synchronized (p) 
					{
						p.notifyAll();
				    }
				}
			}
			else if(type == CommonConstants.FOLD)
			{
				if(socketHandler.getPokerplayer().getCurplaytable().containsKey(tableid))
				{
					Player p = socketHandler.getPokerplayer().getCurplaytable().get(tableid);
					p.setAction( Action.FOLD);
					synchronized (p) 
					{
						p.notifyAll();
				    }
				}
			}
			else if(type == CommonConstants.RAISE)
			{
				if(socketHandler.getPokerplayer().getCurplaytable().containsKey(tableid))
				{
					int amount =  jsonobject.getInt("amount");
					Player p = socketHandler.getPokerplayer().getCurplaytable().get(tableid);
					p.setAction( new RaiseAction(amount));
					synchronized (p) 
					{
						p.notifyAll();
				    }
				}
			}
			else if(type == CommonConstants.SMALL_BLIND)
			{
				if(socketHandler.getPokerplayer().getCurplaytable().containsKey(tableid))
				{
					Player p = socketHandler.getPokerplayer().getCurplaytable().get(tableid);
					p.setAction( Action.SMALL_BLIND);
					synchronized (p) 
					{
						p.notifyAll();
				    }
				}
			}
			else if(type == CommonConstants.BIG_BLIND)
			{
				if(socketHandler.getPokerplayer().getCurplaytable().containsKey(tableid))
				{
					Player p = socketHandler.getPokerplayer().getCurplaytable().get(tableid);
					p.setAction( Action.BIG_BLIND);
					synchronized (p) 
					{
						p.notifyAll();
				    }
				}
			}
			else if(type == CommonConstants.CONTINUE)
			{
				if(socketHandler.getPokerplayer().getCurplaytable().containsKey(tableid))
				{
					Player p = socketHandler.getPokerplayer().getCurplaytable().get(tableid);
					p.setAction( Action.CONTINUE);
					synchronized (p) 
					{
						p.notifyAll();
				    }
				}
			}
		}

	}
}

